package game.worlds;

import hx.utils.SoundManager;
import game.worlds.HideCoollision;
import game.modes.ModeManage;
import hx.utils.SceneManager;
import game.data.GameFightAnalysisLogData;
import game.data.GameOption;
import haxe.Timer;
#if game
import game.views.RoleLogView;
import game.views.FightStateView;
import game.views.LoadRoleView;
import game.data.XlsData;
#end
import game.event.WorldEvent;
import echo.math.Vector2;
import echo.Body;
import hx.events.Event;
import hx.display.MovieClip;
import game.event.RoleEvent;
import game.script.AiScript;
import hx.display.HBox;
import game.views.CDDisplay;
import game.utils.KeybarodTools;
import hx.display.Image;
import motion.Actuate;
import hx.display.Quad;
import game.assets.ABNDataFuture;
import game.assets.Hxwz2RolePackageFuture;
import game.assets.ABProjFuture;
import game.assets.HxwzAssets;
import hx.display.DisplayObject;
import hx.geom.Rectangle;
import hx.ui.UIManager;
import game.data.WorldObjectData;
import hx.display.Box;
import hx.display.Scene;
import game.worlds.RoleActionEffect;

/**
 * 游戏战斗场景
 */
class GameWorld extends World {
	/**
	 * 当前运行的世界
	 */
	public static var currentWorld:GameWorld;

	/**
	 * 世界的速度比
	 */
	public static var worldSpeedScale:Float = 1;

	/**
	 * 状态栏
	 */
	public var state:IStateView;

	/**
	 * 世界项目数据
	 */
	public var worldObjectData:WorldObjectData;

	/**
	 * 游戏世界参数
	 */
	public var option:GameWorldOption;

	/**
	 * 状态栏调试器开关
	 */
	public var stateDebug:Bool = false;

	/**
	 * 地图ID
	 */
	public var mapId:String = "map1";

	public var gameAssets:HxwzAssets;

	public function new(?option:GameWorldOption) {
		super();
		this.option = option;
		this.assets = new game.assets.HxwzAssets();
		this.gameAssets = cast this.assets;
	}

	/**
	 * 资源加载统一入口实现，请在此方法通过`assets`加载资源
	 */
	override public function onAssetsLoad():Void {
		#if game
		__loadRoleView = new LoadRoleView();
		#end
		// 加载资源
		var mapFuture = new game.assets.WorldMapDataFuture("assets/worlds/" + mapId + ".json");
		// 加载地图音频
		#if game
		this.assets.loadSound("assets/sounds/" + mapId + ".mp3");
		#end
		mapFuture.world = this;
		assets.pushFuture(mapFuture);
		// 加载头像
		for (role in this.option.roles) {
			var path = role.path ?? "assets/roles/" + role.id + "." + role.loadType;
			switch role.loadType {
				case HXWZ2_DATA:
					assets.pushFuture(new Hxwz2RolePackageFuture(path));
				case ABN_DATA:
					assets.pushFuture(new ABNDataFuture(path));
				case ABPROJ:
					assets.pushFuture(new ABProjFuture(path));
			}
			#if game
			// 加载头像
			// if (!stateDebug)
			var roleData = XlsData.roles.getDataByRoleid(role.id);
			if (roleData != null) {
				assets.loadBitmapData("assets/icons/roles/" + role.id + ".png");
			}
			#end
		}
		// 通用音效
		assets.loadSound("assets/sounds/blowhit.mp3"); // 已实装
		assets.loadSound("assets/sounds/defense.mp3"); // 已实装
		assets.loadSound("assets/sounds/jump.mp3"); // 已实装
		assets.loadSound("assets/sounds/jumped.mp3"); // 已实装
		assets.loadSound("assets/sounds/ready.mp3");
		assets.loadSound("assets/sounds/fight.mp3");
		assets.loadSound("assets/sounds/ko.mp3");

		assets.loadUIAssets("assets/views/FightStateView.xml");
		assets.loadAtlas("assets/effects/hit1.png", "assets/effects/hit1.xml");
		// 重击在地面上产生的特效
		assets.loadAtlas("assets/effects/boom_hit2.png", "assets/effects/boom_hit2.xml");
		// 跳跃特效
		assets.loadAtlas("assets/effects/jump.png", "assets/effects/jump.xml");
		assets.loadAtlas("assets/effects/jump2.png", "assets/effects/jump2.xml");
		// 防御特效
		assets.loadAtlas("assets/effects/defense.png", "assets/effects/defense.xml");
		assets.loadAtlas("assets/effects/defense2.png", "assets/effects/defense2.xml");
		// 背击特效
		assets.loadAtlas("assets/effects/backhit.png", "assets/effects/backhit.xml");
		// 重打击特效
		assets.loadAtlas("assets/effects/boom_hit1.png", "assets/effects/boom_hit1.xml");
		// 伤害数字
		assets.loadFnt("assets/ui/atlas/hurt_number.png", "assets/ui/atlas/hurt_number.fnt");
		// 魔法伤害数字
		assets.loadFnt("assets/ui/atlas/hurt_number2.png", "assets/ui/atlas/hurt_number2.fnt");
		// 恢复血量数字
		assets.loadFnt("assets/ui/atlas/hurt_number3.png", "assets/ui/atlas/hurt_number3.fnt");
		// 真实伤害数字
		assets.loadFnt("assets/ui/atlas/hurt_number4.png", "assets/ui/atlas/hurt_number4.fnt");
		// ready and fight
		assets.loadAtlas("assets/ui/atlas/round_pk.png", "assets/ui/atlas/round_pk.xml");
		// 加载键盘图集
		assets.loadAtlas("assets/ui/atlas/keys_atlas.png", "assets/ui/atlas/keys_atlas.xml");
		// 加载CD动画
		assets.loadAtlas("assets/ui/atlas/cdline.png", "assets/ui/atlas/cdline.xml");
		// 加载KO动画
		assets.loadAtlas("assets/ui/atlas/KO.png", "assets/ui/atlas/KO.xml");
		// 时间过时处理
		assets.loadBitmapData("assets/ui/imgs/time_over.png");
		// 加载1P 2P
		assets.loadBitmapData("assets/ui/imgs/player1.png");
		assets.loadBitmapData("assets/ui/imgs/player2.png");

		#if game
		__loadRoleView.bindWorld(this, [LoadRoleView.createLoadRoleViewPlayer(this.option.player1)],
			[LoadRoleView.createLoadRoleViewPlayer(this.option.player2)]);
		#end
	}

	#if game
	private var __loadRoleView:LoadRoleView;
	#end

	/**
	 * 局数
	 */
	public var roundTimes:Int = 0;

	public function onRoleCreate():Void {}

	override function onGameStart() {
		super.onGameStart();
		#if game
		if (!__loadRoleView.isLoaded()) {
			// 等待加载器加载完毕后再调用
			return;
		}
		SoundManager.getInstance().playBGMSound(mapId);
		#end
		this.isGameOver = false;
		// 地图解析
		this.parserWorldData();
		roundTimes++;

		#if game
		var fightState:game.views.FightStateView = cast this.state;
		if (fightState == null) {
			fightState = new game.views.FightStateView(this);
			fightState.setDebug(stateDebug);
			fightState.timeout = option.time ?? -1;
			state = fightState;
			this.addChild(cast state);
		}
		#end

		this.onRoleCreate();

		// for (i in 0...50) {
		// 	var role = new GameRole(this, gameAssets.roles.get(this.option.player2));
		// 	role.x = Math.random() * 400;
		// 	role.y = 300;
		// 	role.troop = 1;
		// 	this.addDisplay(role);
		// }

		this.mathCamrea(0, 1);

		KeybarodTools.enable = false;

		Actuate.tween(quad, 0.5, {alpha: 0}).onComplete(function() {
			quad.remove();
			if (#if game true #else !stateDebug #end) {
				// 进入准备、战斗动画
				var ready = new HBox();
				ready.gap = 30;
				this.addChild(ready);
				var img = new Image(assets.getBitmapData("round_pk:round"));
				ready.addChild(img);
				var img = new Image(assets.getBitmapData("round_pk:num" + roundTimes));
				ready.addChild(img);

				ready.originX = -ready.width / 2;
				ready.originY = -ready.height / 2;
				ready.x = stage.stageWidth / 2;
				ready.y = stage.stageHeight * 0.4;
				ready.scaleX = ready.scaleY = 0;

				SoundManager.getInstance().playEffect("ready");

				Actuate.tween(ready, 0.5, {scaleX: 1.5, scaleY: 1.5}).onComplete(() -> {
					Actuate.tween(ready, 0.5, {alpha: 0}).onComplete(() -> {
						ready.remove();
						var img2 = new Image(assets.getBitmapData("round_pk:fight"));
						this.addChild(img2);
						img2.originX = -img2.width / 2;
						img2.originY = -img2.height / 2;
						img2.x = stage.stageWidth / 2;
						img2.y = stage.stageHeight * 0.4;
						img2.scaleX = img2.scaleY = 0;
						Actuate.tween(img2, 0.5, {scaleX: 1.5, scaleY: 1.5}).onComplete(() -> {
							Actuate.tween(img2, 0.5, {alpha: 0}).onComplete(() -> {
								img2.remove();
							}).delay(0.5);
						});
						KeybarodTools.enable = true;
						SoundManager.getInstance().playEffect("fight");
					}).delay(0.5);
				});
			} else {
				KeybarodTools.enable = true;
			}
		});
	}

	public var quad:Quad = new Quad();

	override function onStageInit() {
		super.onStageInit();

		currentWorld = this;

		quad.width = this.stage.stageWidth;
		quad.height = this.stage.stageHeight;
		this.addChild(quad);

		this.addEventListener(RoleEvent.DEAD, onDead);
		this.addEventListener(WorldEvent.TIME_OVER, onTimeOver);

		// 呈现加载界面
		#if game
		this.addChild(__loadRoleView);
		#end
	}

	private function onTimeOver(e:WorldEvent):Void {
		if (isGameOver)
			return;
		trace("游戏时间结束");
		isGameOver = true;
		var timeOverImage = new Image(this.assets.getBitmapData("time_over"));
		this.addChild(timeOverImage);
		timeOverImage.scaleX = timeOverImage.scaleY = 2;
		timeOverImage.x = (this.stage.stageWidth - timeOverImage.width) / 2;
		timeOverImage.y = (this.stage.stageHeight - timeOverImage.height) / 2 - stage.stageHeight;
		Actuate.tween(timeOverImage, 1, {
			y: (this.stage.stageHeight - timeOverImage.height) / 2
		}).onComplete(() -> {
			// 计算胜利结果
			var role1p = this.roles[0];
			var role2p = this.roles[1];
			if (role1p.data.hp == role2p.data.hp) {
				// 平手，双方都得分
				cast(this.state, DisplayObject).dispatchEvent(new Event("winState", false, false, role1p));
				cast(this.state, DisplayObject).dispatchEvent(new Event("winState", false, false, role2p));
			} else if (role1p.data.hp > role2p.data.hp) {
				// 角色1胜利
				cast(this.state, DisplayObject).dispatchEvent(new Event("winState", false, false, role1p));
			} else {
				// 角色2胜利
				cast(this.state, DisplayObject).dispatchEvent(new Event("winState", false, false, role2p));
			}
			Actuate.tween(timeOverImage, 1, {
				alpha: 0
			}).onComplete(() -> {
				this.removeChild(timeOverImage);
				this.resetNextGame();
			}).delay(1);
		});
	}

	/**
	 * 开始下一把游戏
	 */
	public function resetNextGame():Void {
		this.quad.alpha = 0;
		quad.width = this.stage.stageWidth;
		quad.height = this.stage.stageHeight;
		this.addChild(this.quad);
		Actuate.tween(this.quad, 0.5, {alpha: 1}).onComplete(() -> {
			#if game
			#end
			this.restart();
		});
	}

	/**
	 * 是否为游戏结束
	 */
	public var isGameOver(default, set):Bool = false;

	private function set_isGameOver(v:Bool):Bool {
		this.isGameOver = v;
		if (v) {
			KeybarodTools.enable = false;
			for (role in roles) {
				role.releaseAllKeys();
			}
		}
		return v;
	}

	private function onDead(e:RoleEvent) {
		if (isGameOver)
			return;
		trace("有角色死亡，需要检测是否结束游戏");
		var existRoles = roles.filter(role -> role.data.hp > 0);
		if (existRoles.length <= 1) {
			trace("游戏结束");
			isGameOver = true;
			worldSpeedScale = 0.3;
			Actuate.tween(this, 1.5, {
				worldSpeedScale: 1
			}, false).onComplete(() -> {
				// 展示OK动画
				worldSpeedScale = 1;
				SoundManager.getInstance().playEffect("ko");
				var koAnimte = new MovieClip(this.assets.atlases.get("KO").getBitmapDatasByName());
				this.addChild(koAnimte);
				koAnimte.x = stage.width / 2;
				koAnimte.y = stage.height / 2;
				koAnimte.originX = -koAnimte.width / 2;
				koAnimte.originY = -koAnimte.height / 2;
				koAnimte.scaleX = koAnimte.scaleY = 6;
				koAnimte.play(1);
				koAnimte.addEventListener(Event.COMPLETE, (e) -> {
					koAnimte.remove();
					// 这个时候需要判断是否要进入下一轮比赛
					if (existRoles.length == 1) {
						var role = existRoles[0];
						cast(this.state, DisplayObject).dispatchEvent(new Event("winState", false, false, role));
						this.resetNextGame();
					}
				});
				koAnimte.alpha = 0;
				Actuate.tween(koAnimte, 0.5, {
					alpha: 1,
					scaleX: 4,
					scaleY: 4
				});
			});
		}
	}

	override function advance(dt:Float) {
		dt = dt * worldSpeedScale;

		super.advance(dt);

		for (display in this.displayBox.children) {
			if (display is IAttackDisplay) {
				var attack:IAttackDisplay = cast display;
				var isHited = false;
				for (checkRole in roles) {
					if (attack != checkRole && attack.troop != checkRole.troop && !checkRole.isInvincible) {
						if (attack.currentHitColliderFrameData != null) {
							if (attack.currentHitColliderFrameData.hitData.attackInterval == 0
								|| attack.currentHitColliderFrameData.hitData.hitedTime == 0
								|| attack.nowTime - attack.currentHitColliderFrameData.hitData.hitedTime > attack.currentHitColliderFrameData.hitData.attackInterval) {
								if (attack.currentHitColliderFrameData.testCollision(attack, checkRole.hitBody.shape)) {
									// 这里需要产生击中效果
									checkRole.applyHitData(attack, attack.currentHitColliderFrameData.hitData, attack.hitScaleX);
									isHited = true;
								}
							}
						}
					}
				}
				if (isHited) {
					if (attack.currentHitColliderFrameData != null) {
						if (attack.currentHitColliderFrameData.hitData.attackInterval == 0) {
							attack.currentHitColliderFrameData = null;
						} else {
							// 标记击中时间
							attack.currentHitColliderFrameData.hitData.hitedTime = attack.nowTime;
						}
					}
					#if game
					state.showComboHit(attack.getRole());
					#end
				}
			}
		}
		// 地图碰撞
		// for (role in roles) {
		// 	role.hitMap(mapDisplays);
		// }
		// 角色排斥计算
		for (role in roles) {
			role.repelRoles(roles, dt);
		}
		this.onEchoUpdate(dt);
		for (role in roles) {
			@:privateAccess role.onHitMap(dt);
		}
		this.mathCamrea(dt);
	}

	public function mathCamrea(dt:Float, tween:Float = 0.15):Void {
		if (roles.length > 0) {
			// 摄像机处理
			var rect = mathRolesRect();
			var scale = Math.min(3.3, Math.min((stage.stageWidth - 40) / rect.width, (stage.stageHeight - 140) / rect.height));
			camera.update(rect.x + rect.width / 2, rect.y + rect.height / 2, scale, dt, tween);
		}
	}

	override public function onDebugDraw() {
		for (object in displayBox.children) {
			if (object is IDisplay) {
				var display = cast(object, IDisplay);
				if (display.hitBody != null) {
					for (shape in display.hitBody.shapes) {
						this.__echoDebug.draw_shape(shape);
					}
				}
			}
			if (object is IAttackDisplay) {
				var display = cast(object, IAttackDisplay);
				if (display.currentHitColliderFrameData != null && display.currentHitColliderFrameData.collision != null) {
					for (shape in display.currentHitColliderFrameData.collision.shapes) {
						this.__echoDebug.draw_shape(shape);
					}
				}
			}
		}
	}

	/**
	 * 获得当前所有角色矩形
	 * @return Rectangle
	 */
	public function mathRolesRect():Rectangle {
		var scale = 0.;
		var yMaths = this.roles.map(function(role) {
			return role.y;
		});
		yMaths.sort((a, b) -> a > b ? 1 : -1);
		var yMin = yMaths[0];
		var yMax = yMaths[yMaths.length - 1];
		var yLen = yMax - yMin;
		scale = Math.min(1, yLen / 100);
		var rect = new Rectangle();
		for (role in this.roles) {
			rect.expand(role.x - 10, role.y - 70 + 30 * scale, 20, 70);
		}
		return rect;
	}

	/**
	 * 地图最下面的坐标，一般用来计算角色的站位使用
	 */
	public var maxWorldY:Float = 0;

	/**
	 * 解析地图数据
	 * @param id 
	 */
	private function parserWorldData():Void {
		// 初始化Echo碰撞地图数据
		this.initEchoWorld({width: 800, height: 600, gravity_y: 0});
		// this.initEchoWorld({width: 800, height: 600, gravity_y: 1500});
		var mapData = assets.objects.get("map");
		var subWorlds:Array<Dynamic> = mapData.subWorlds;
		function applyDisplay(display:DisplayObject, data:Dynamic):Void {
			display.x = data.x;
			display.y = data.y;
			display.rotation = data.rotation;
			display.scaleX = data.scaleX;
			display.scaleY = data.scaleY;
			display.name = data.name;
		}
		var maxY = 0.;
		for (sub in subWorlds) {
			var boxDisplays:Array<Dynamic> = sub.boxDisplays;
			for (d in boxDisplays) {
				var name:String = d.name;
				if (name != null && name.indexOf("bg_") == 0) {
					// 背景配置，需要键入到背景中
					var bg = new BGDisplay(assets.getBitmapData(d.id));
					this.addChildAt(bg, 0);
					bgDisplays.push(bg);
					applyDisplay(bg, d);
					bg.x = bg.y = 0;
				} else {
					var type:String = "game.worlds.MapDisplay";
					var objData = worldObjectData.getConfig(d.id);
					if (objData.classType != null && objData.classType != "") {
						type = objData.classType;
					}
					var image:MapDisplay = Type.createInstance(Type.resolveClass(type), [assets.getBitmapData(d.id)]);
					this.mapBox.addChild(image);
					mapDisplays.push(image);
					image.world = this;
					applyDisplay(image, d);
					var body = worldObjectData.createEchoCollision(d.id);
					if (body != null) {
						body.set_position(image.x, image.y);
						body.scale_x = image.scaleX;
						body.scale_y = image.scaleY;
						body.rotation = image.rotation;
						image.body = body;
						this.addMapDisplay(image);
						maxY = Math.max(maxY, image.body.bounds().min_y);
					}
				}
			}
			mapWidth = sub.width;
			mapHeight = sub.height;
			break;
		}
		this.echoWorld.width = mapWidth;
		this.echoWorld.height = mapHeight;

		// 默认创建两边的墙
		statisBoids.push(this.echoWorld.make({
			mass: STATIC,
			x: -40,
			y: 0,
			shape: {
				type: POLYGON,
				vertices: [
					new Vector2(0, 0),
					new Vector2(80, 0),
					new Vector2(80, mapHeight),
					new Vector2(0, mapHeight)
				]
			}
		}));
		statisBoids.push(this.echoWorld.make({
			mass: STATIC,
			x: mapWidth - 40,
			y: 0,
			shape: {
				type: POLYGON,
				vertices: [
					new Vector2(0, 0),
					new Vector2(80, 0),
					new Vector2(80, mapHeight),
					new Vector2(0, mapHeight)
				]
			}
		}));
		// 创建底下的墙
		var body = this.echoWorld.make({
			mass: STATIC,
			x: 0,
			y: maxY,
			shape: {
				type: POLYGON,
				vertices: [
					new Vector2(0, 0),
					new Vector2(mapWidth, 0),
					new Vector2(mapWidth, 100),
					new Vector2(0, 100)
				]
			}
		});
		this.maxWorldY = maxY;
		body.entity = new MapDisplay();
		body.entity.name = "unjump";
		mapBoids.push(body);
	}

	/**
	 * 战斗分析数据
	 */
	public var gameFightAnalysisLogData:GameFightAnalysisLogData = new GameFightAnalysisLogData();
}
